package org.visionlibrary.image.geomtric.lines.histogram;

import java.util.List;

import org.visionlibrary.image.geomtric.lines.histogram.model.AbstractLinesHistogram;
import org.visionlibrary.image.geomtric.model.Point2d;
import org.visionlibrary.image.geomtric.model.Vector2d;
import org.visionlibrary.image.model.Histogram;


/**
 * Klasa realizujaca generowanie histogramu dla zbioru odcinkow na podstawie ich
 * srodka ciezkosci, kazdy odcinek dzielony jest na rowna ilosc punktow. Pomiedzy
 * kazdym z tak wyznaczonych punktow a srodkiem ciezkosci wyznaczny jest tymczasowy
 * odcinek, algorytm sumuje dlugosc takich utworzonych odcinkow i umieszcza je
 * w koszyku odziwerciedlajacym kat jego nachylenia.
 */
public class CenterOfGravityLineSlope extends
		AbstractLinesHistogram {
	protected int histogramSize = 10000;
	protected Point2d centroid = null;
	
	public CenterOfGravityLineSlope(Point2d centroid,
			int histogramSize) {
		super();
		this.centroid = centroid;
		this.histogramSize = histogramSize;
	}

	@Override
	public Histogram process(List<Vector2d> lines) {
		if (null == lines)
			throw new NullPointerException("Lines list is null.");

		Histogram histogram = new Histogram(histogramSize + 1);
		
		for (Vector2d line : lines) {			
			Point2d pointA = line.getFirst();
			Point2d pointB = line.getLast();

			Vector2d first = new Vector2d(centroid, pointA);
			Vector2d last = new Vector2d(centroid, pointB);

			double angleDiff = first.angle() - last.angle();
			double angleDeg = Math.ceil(Math.abs(Math.toDegrees(angleDiff)));
			
			Point2d atmp = Point2d.multiply(pointA, 1.0d / angleDeg);
			Point2d btmp = Point2d.multiply(pointB, 1.0d / angleDeg);

			Point2d hookedp = new Point2d(btmp.x - atmp.x, btmp.y - atmp.y);

			for (double i = 0; i <= angleDeg; i++) {
				Point2d di = Point2d.move(pointA, i * hookedp.x, i * hookedp.y);
				Vector2d vector = new Vector2d(centroid, di);
				double angle = vector.angle(true);
				int index = (int) t(angle, histogramSize);
				histogram.addToBin(index, vector.length());
			}
		}

		return histogram;
	}
	
	private double t(double angle, int precision) {
		double maxtheta = 2 * Math.PI;
		double thetadiff = maxtheta - angle;
		return precision - (precision * thetadiff / maxtheta);
	}
}
